// 
//  ScannerOption.cs
//  
//  Author:
//       Christopher Sawyer <christoofar@gmail.com>
// 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
// 
//  You should have received a copy of the GNU Lesser General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections;
using System.Collections.Generic;

namespace Mono.SANE
{

	/// <summary>
	/// Describes a particular capability of a scanner
	/// </summary>
	public class ScannerOption
	{
		private string _switch = "";
		private string[] _availableOptions;
		private string _currentSetting = "";
		
		/// <summary>
		/// The SANE backend switch for this scanner option
		/// </summary>
		public string Switch {
			get {
				return _switch;
			}
		}
		
		
		/// <summary>
		/// The current value this option is set to
		/// </summary>
		public string CurrentSetting {
			get {
				return _currentSetting;
			}
			set {
				SetOption (value);
			}
		}
		
		
		/// <summary>
		/// Where available, a list of available options to select from for this switch
		/// </summary>
		public string[] AvailableOptions {
			get {
				return _availableOptions;
			}
		}
		
		/// <summary>
		/// Applies a SANE setting for this option.  Option must be expressed exacty as specified in AvailableOptions
		/// or an InvalidScannerOptionException will be raised.
		/// </summary>
		/// <param name="setting">
		/// A <see cref="System.String"/>
		/// </param>
		public void SetOption (string setting)
		{
			if (setting.ToLower () == "inactive" || setting.ToLower () == "not used" 
				|| setting.ToLower() == "default")
			{
				return;
			}
			
			if (_availableOptions != null && _availableOptions.Length > 0)
			{
				bool found = false;
				
				foreach (string option in _availableOptions)
				{
					if (option == setting)
					{
						found = true;
						break;
					}
				}
				
				if (!found)
				{
					InvalidDataDetected(Switch, setting, _availableOptions);
				}
			}
			
			_currentSetting = setting;
		}
		
		private void InvalidDataDetected (string settingName, string settingValue)
		{
			throw new InvalidOperationException ("An invalid option [" + settingName + 
				"] was set with value " + settingValue + ".");
		}
		
		private void InvalidDataDetected (string settingName, string settingValue, string[] availableOptions)
		{
			throw new InvalidOperationException ("An invalid option [" + settingName + 
				"] was set with value " + settingValue + ". " + "The valid options are: " + 
				string.Join (",", availableOptions));			
		}

		private ScannerOption ()
		{
		}
		
		/// <summary>
		/// Creates a new instance of <see cref="ScannerOption"/>
		/// </summary>
		/// <param name="switchName">
		/// A <see cref="System.String"/>
		/// </param>
		/// <param name="availableOptions">
		/// A <see cref="System.String[]"/>
		/// </param>
		/// <param name="currentSetting">
		/// A <see cref="System.String"/>
		/// </param>
		public ScannerOption (string switchName, string[] availableOptions, string currentSetting)
		{
			_switch = switchName;
			
			List<string> options = new List<string> ();
			foreach (string option in availableOptions)
			{
				if (!option.ToLower().Equals ("default")) 
				{
					options.Add(option);
				}
			}
			
			_availableOptions = options.ToArray();
			CurrentSetting = currentSetting;
		}
	}
	
	/// <summary>
	/// Raised whenever a user sets an inappropriate value for a SANE setting for a defined imaging device
	/// </summary>
	public class InvalidScannerOption: Exception
	{
	}
	
}
